#region (c) 2009 Abdullin.com and Contributors

// Copyright (c) 2009 Abdullin.com and Contributors
// Site: http://abdullin.com/ncouch
// This code is released under the terms of the new BSD licence

#endregion

using System;
using System.IO;
using Lokad;
using NCouch.Model;

namespace NCouch
{
	public sealed class CouchDatabase : CouchAdapterBase
	{
		public CouchDatabase(CouchRestClient client) : base(client) {}

		public RevisionInfo SaveDocument<T>(T item, Func<T, Guid> id)
		{
			var query = id(item).ToString();
			return SaveDocument(item, query);
		}

		public RevisionInfo SaveDocument<T>(T item, string name)
		{
			using (var response = Put(name, x => x.WithContent(item)))
			{
				Fail(response).Unless(CouchStatus.Code201);
				return ReadObject<RevisionInfo>(response);
			}
		}

		public RevisionInfo AddAttachment(RevisionInfo info, string name, Action<Stream> data, string contentType)
		{
			var query = string.Format("{0}/{1}?rev={2}", info.Id, name, info.Revision);

			using (var response = Put(query, x => x.WithStream(data, contentType)))
			{
				return ReadObject<RevisionInfo>(response);
			}
		}

		public string GetAttachment(RevisionInfo info, string name, Action<Stream> reader)
		{
			var query = string.Format("{0}/{1}?rev={2}", info.Id, name, info.Revision);
			using (var r = Get(query))
			{
				r.RunReader(reader);
				return r.ContentType;
			}
		}

		public RevisionInfo DeleteAttachment(RevisionInfo info, string attachmentName)
		{
			var query = string.Format("{0}/{1}?rev={2}", info.Id, attachmentName, info.Revision);
			using (var response = Delete(query))
			{
				Fail(response).Unless(CouchStatus.Code200);
				return ReadObject<RevisionInfo>(response);
			}
		}

		// todo - switch to strong results
		public T GetDocument<T>(string id)
		{
			using (var r = Get(id))
			{
				Fail(r).Unless(CouchStatus.Code200);
				return ReadObject<T>(r);
			}
		}

		public View<TKey, TValue> GetTempView<TKey, TValue>(MapView view)
		{
			using (var r = Post("_temp_view", x => x.WithContent(view)))
			{
				return ReadObject<View<TKey, TValue>>(r);
			}
		}

		public View<Guid, TValue> GetTempView<TValue>(MapView view)
		{
			return GetTempView<Guid, TValue>(view);
		}

		public DatabaseInfo GetInfo()
		{
			using (var r = Get(""))
			{
				return ReadObject<DatabaseInfo>(r);
			}
		}
	}
}